#include <stdio.h>		/* ANSI C standard input/output library */
#include <stdarg.h>		/* ANSI C standard arguments library */
#include "vpi_user.h"		/* IEEE 1364 PLI VPI routine library  */
#include "assert.h"
#include "misc.h"

#include "pli_interface.h"
#include "params.h"
#include "ultraMips.h"

int pli_init()
{
	int success = get_options();
	if (!success)
		vpi_control(vpiFinish, 1);
	params.cycles = 0;
	clear_input_ports();
	return 0;
}

int pli_capture()
{

	ports_o.inst_o_valid = get_scalar_value("bench.dut.inst_o_valid");
	ports_o.inst_o_addr = get_int_value("bench.dut.inst_o_addr");

	ports_o.mem_o_line_valid = get_int_value("bench.dut.mem_o_line_valid");
	ports_o.mem_o_ctrl = get_int_value("bench.dut.mem_o_ctrl");
	ports_o.mem_o_addr = get_int_value("bench.dut.mem_o_addr");
	ports_o.mem_o_dest_reg = get_int_value("bench.dut.mem_o_dest_reg");
	ports_o.mem_o_data = get_int_value ("bench.dut.mem_o_data");
	return 0;
}

int pli_update()
{
	int error_list[20] = {0};
    char *signal_names[7] = { "inst_o_valid", "inst_o_addr", "mem_o_data", "mem_o_addr", "mem_o_dest_reg", "mem_o_ctrl", "mem_o_line_valid"};
	//generating golden c model outputs
	int stop_flag = 0;
	ultramips();
	// processs DUT outputs, compare against C model
	compare(&error_list);

	// report errors, if any 

	if (params.cycles < params.max_cycles) 
	{
		int i;
		for(i = 0;i<7;i++)
			{
				if(error_list[i] == 0)
					{
						vpi_printf("ERROR: at %lld cycle: %s\n",params.cycles, signal_names[i]);
						error_list[i] = 0;
					}
			}
	}
if(params.cycles >= params.max_cycles)
	{
		vpi_printf ("Test ended after %lld cycles\n",params.max_cycles);
		vpi_control(vpiFinish, 1);
	}
	
	clear_input_ports();
	// set DUT inputs for next cycle
	params.cycles++;
	
	set_reset();
	set_inst_i_valid();
	set_inst_i_line();
	set_mem_i_all();
	
	return 0;
}

int pli_drive()
{

	set_scalar_value("bench.dut.resetn", ports_i.reset);
	set_scalar_value("bench.dut.inst_i_valid", ports_i.inst_i_valid);
	set_u64_value("bench.dut.inst_i_line", ports_i.inst_i_line);
	
	set_u64_value("bench.dut.mem_i_line", ports_i.mem_i_line);
	set_int_value("bench.dut.mem_i_dest_m", ports_i.mem_i_dest_m);
	set_scalar_value("bench.dut.mem_i_ctrl_m", ports_i.mem_i_ctrl_m);
	set_int_value("bench.dut.mem_i_line_valid_m", ports_i.mem_i_line_valid_m);
	
	return 0;
	
}
